//
//  RobotScene.m
//  iSuDoku
//
//  Created by maccctk on 09-7-8.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//

#import <AudioToolbox/AudioToolbox.h>
#import "MenuScene.h"
#import "Question.h"
#import "RobotScene.h"

#define XOFF							26
#define YOFF							24
#define XGAP							33
#define YGAP							33


@implementation RobotScene

- (id)init {
	NSLog(@"RobotScene init");
	
	self = [super init];
	if(self != nil) {
		Sprite *bg = [Sprite spriteWithFile:@"game.png"];
		[bg setPosition:ccp(240, 160)];
		[self addChild:bg z:0];
		
		Sprite *board = [Sprite spriteWithFile:@"board.png"];
		[board setPosition:ccp(160, 160)];
		[self addChild:board z:0];
		
		Sprite *cmdSprite = [Sprite spriteWithFile:@"cmd.png"];
		[cmdSprite setPosition:ccp(420, 106)];
		[self addChild:cmdSprite z:0];
		
		Sprite *note = [Sprite spriteWithFile:@"note.png"];
		[note setPosition:ccp(350, 202)];
		[self addChild:note z:0];
		
		Sprite *sp = [Sprite spriteWithFile:@"sprite.png"];
		[sp setPosition:ccp(340, 260)];
		[self addChild:sp z:0];
		
		RobotScene *rs = [RobotLayer node];
		[self addChild:rs z:0];		
	}
	return self;
}

@end

@implementation RobotLayer

- (void)get_digit_xy:(int)n :(int *)x :(int *)y {
	*x = XOFF + (n % 9) * XGAP + (n % 9) / 3;
	*y = YOFF + (8 - n / 9) * YGAP + (8 - n / 9) / 3;
}

- (void)get_keyboard_xy:(int)n :(int *)x :(int *)y {
	*x =  20 + (n % 3) * 40;
	*y =  15 + (3 - n / 3) * 30;
	if(n >= 9)
		*x += 40;
}

- (void)get_cmd_xy:(int)n :(int *)x :(int *)y {
	*x = 0;
	*y = (6 - n) * 30;
}

- (void)initCmd {
	char *cmdList[] = { "alpha", "tosolv", "reset", "final", "new", "main", nil };
	int x, y, i;
	
	Menu *menu = [Menu menuWithItems:nil];
	for(i = 0 ; cmdList[i] != nil ; i ++) {
		NSString *str;
		str = [[NSString alloc] initWithFormat:@"%s", cmdList[i]];
		
		citem[i] = [MenuItemFont itemFromString:str target:self selector:@selector(cmdClicked:)];
		[citem[i] setRelativeTransformAnchor:NO];
		Label *label = citem[i].label;
		[label initWithString:str dimensions:CGSizeMake(60,20) alignment:UITextAlignmentLeft fontName:@"Helvetica" fontSize:11];
		[label setRGB:0 :0 :0x80];				
		
		[self get_cmd_xy:i :&x :&y];
		[citem[i] setPosition:ccp(x, y)];
		[menu addChild:citem[i]];
	}
	[menu setPosition:ccp(450, 40)];
	[self addChild:menu z:2];	
}

- (void)updateCmd {
	NSString *str;
	
	if(is_alpha_doku)
		str = @"digit";
	else
		str = @"alpha";
	
	[citem[0].label setString:str];
}

- (void)initKeyboard {
	int x, y, i;
	
	keypad = [Sprite spriteWithFile:@"keypad.png"];
	[keypad setRelativeTransformAnchor:NO];
	[keypad setPosition:ccp(1000,1000)];
	keypad.visible = NO;
	[self addChild:keypad z:2];
	
	kmenu = [Menu menuWithItems:nil];
	for(i = 0 ; i < 10 ; i ++) {
		NSString *str2 = @"W";
		
		kitem[i] = [MenuItemFont itemFromString:str2 target:self selector:@selector(keyboardClicked:)];
		Label *label = kitem[i].label;
		if(i < 9)
			[label initWithString:str2 dimensions:CGSizeMake(40,30) alignment:UITextAlignmentCenter fontName:@"Helvetica" fontSize:24];
		else
			[label initWithString:str2 dimensions:CGSizeMake(120,30) alignment:UITextAlignmentCenter fontName:@"Helvetica" fontSize:24];
		
		[label setRGB:0 :0 :0x80];
		
		[self get_keyboard_xy:i :&x :&y];
		[kitem[i] setPosition:ccp(x, y)];
		[kmenu addChild:kitem[i]];
		
		char c;
		if(is_alpha_doku)
			c = 'A';
		else
			c = '1';
		
		NSString *str;
		if(i < 9)
			str = [[NSString alloc] initWithFormat:@"%c", c+i];
		else
			str = [[NSString alloc] initWithFormat:@"c"];
		
		[kitem[i] setString:str];
	}
	
	[kmenu setRelativeTransformAnchor:NO];
	[kmenu setPosition:ccp(1000, 1000)];
	kmenu.visible = NO;
	
	[keypad setOpacity:210];
	[kmenu setOpacity:210];
	
	[self addChild:kmenu z:3];	
}

- (void)updateKeyboard {
	int i;
	
	for(i = 0 ; i < 9 ; i ++) {
		char c;
		
		if(is_alpha_doku)
			c = 'A';
		else
			c = '1';
		
		NSString *str = [[NSString alloc] initWithFormat:@"%c", c+i];
		
		[kitem[i] setString:str];
	}
}

- (void)initLevel {
	NSString *levelString = [[NSString alloc] initWithFormat:@"Digit Sodoku"];
	levelLabel = [Label labelWithString:levelString fontName:@"Marker Felt" fontSize:11];
	[levelLabel setPosition:ccp(400, 309)];
	
	[levelLabel setRGB:0 :0 :0];
	[self addChild:levelLabel z:0];
}

- (void)updateLevel {
	NSString *levelString;
	
	if(is_alpha_doku)
		levelString = [[NSString alloc] initWithFormat:@"Alpha Sodoku"];
	else
		levelString = [[NSString alloc] initWithFormat:@"Digit Sodoku"];
	
	[levelLabel setString:levelString];
	[levelLabel setRGB:0 :0 :0];
}

- (void)initTime {
	begin_time = time(NULL);
	cur_times = 0;
	
	NSString *timeString = [[NSString alloc] initWithFormat:@"000  min"];
	timeLabel = [Label labelWithString:timeString fontName:@"Marker Felt" fontSize:11];
	[timeLabel setPosition:ccp(346, 200)];
	[timeLabel setRGB:0 :0 :0x80];
	[self addChild:timeLabel z:0];
}

- (void)updateTime {
	int t;
	
	t = (time(NULL) - begin_time) / 60;
	if(t < 0)
		t = 0;
	if(t > 999)
		t = 999;
	
	if(t != cur_times) {
		NSString *timeString = [[NSString alloc] initWithFormat:@"%03d  min", t];
		[timeLabel setString:timeString];
		cur_times = t;
	}
}

- (void)update:(ccTime)dt {
	[self updateTime];
}

- (void)resetTime {
	NSString *timeString = [[NSString alloc] initWithFormat:@"000  min"];
	[timeLabel setString:timeString];
	begin_time = time(NULL);
	cur_times = 0;
}

- (void)initBoard {
	char c;
	int x, y, i;
	
	Menu *menu = [Menu menuWithItems:nil];	
	
	memset(&cur_question, 0, sizeof(cur_question));
	
	for(i = 0 ; i < 81 ; i ++) {
		c = ' ';
		NSString *str = [[NSString alloc] initWithFormat:@"%c", c];
		NSString *str2 = @"W";
		
		ditem[i] = [MenuItemFont itemFromString:str2 target:self selector:@selector(digitClicked:)];
		Label *label = ditem[i].label;
		[label initWithString:str dimensions:CGSizeMake(30,30) alignment:UITextAlignmentCenter fontName:@"Marker Felt" fontSize:26];
		[label setRGB:207 :119 :179];
		[ditem[i] setString:str];
		board[i/9][i%9] = 0;
		
		[self get_digit_xy:i :&x :&y];
		[ditem[i] setPosition:ccp(x, y)];
		[menu addChild:ditem[i]];
	}
	
	[menu setPosition:ccp(0, 0)];
	[self addChild:menu z:0];
}

- (void)updateBoard {
	char c;
	int i;
	
	for(i = 0 ; i < 81 ; i ++) {
		if(cur_question[i] == 0)
			c = ' ';
		else if(is_alpha_doku)
			c = cur_question[i] - 1 + 'A';
		else
			c = cur_question[i] + '0';
		NSString *str = [[NSString alloc] initWithFormat:@"%c", c];
		[ditem[i] setString:str];
	}
}

-(void)playNextSound
{
	NSString *path = [[NSBundle mainBundle] pathForResource:@"next" ofType:@"wav"];
	SystemSoundID soundID;
	AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:path], &soundID);
	AudioServicesPlaySystemSound (soundID);	
}

-(void)playEndSound
{
	NSString *path = [[NSBundle mainBundle] pathForResource:@"end" ofType:@"wav"];
	SystemSoundID soundID;
	AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:path], &soundID);
	AudioServicesPlaySystemSound (soundID);	
}

- (id)init {
	NSLog(@"RobotLayer init");
	self = [super init];
	if(self != nil) {
		question = [Question new];
		[self initKeyboard];
		[self initCmd];
		[self initLevel];
		
		[self initTime];
		[self initBoard];
		[self schedule:@selector(update:) interval:1];
	}
	return self;
}

- (void)dealloc {
	NSLog(@"RobotLayer dealloc");
	[question release];
	[super dealloc];
}

- (void)mainGame {
	NSLog(@"main game");
	MenuScene *ms = [MenuScene node];
	[[Director sharedDirector] replaceScene:ms];
	return;	
}

- (void)fillByHint:(char [9][9])myBoard {
	NSString *str;
	bool bExist;
	int i, j;
	char c;
	
	for(i = 0 ; i < 9 ; i ++)
		for(j = 0 ; j < 9 ; j ++) {
			if(board[i][j])
				continue;
			
			if(! myBoard[i][j])
				continue;
			
			board[i][j] = myBoard[i][j];
			
			if(is_alpha_doku)
				c = 'A' - 1;
			else
				c = '0';
			
			str = [[NSString alloc] initWithFormat:@"%c", c+myBoard[i][j]];
			[ditem[i*9+j] setString:str];
			
			bExist = [self isExisted:i :j :board];
			if(bExist)
				[ditem[i*9+j].label setRGB:0xcc :0x00 :0x00];
			else
				[ditem[i*9+j].label setRGB:43 :0 :233];
			
		}
}

- (void)hintGame {
	NSLog(@"hint game");
	
	char myBoard[9][9];
	int ret;
	
	ret = [question robot:board :&myBoard];
	if(ret)
		return;
	[self fillByHint:myBoard];
}

- (int)resetGame {
	NSLog(@"reset game");
	
	int i;
	
	for(i = 0 ; i < 81 ; i ++)
		board[i/9][i%9] = cur_question[i];
	
	[self unschedule:@selector(update:)];
	[self updateBoard];
	[self resetTime];
	[self schedule:@selector(update:)];
	return 0;
}

- (void)digitClicked:(id)sender {
	if(kmenu.visible == YES)
		return;
	
	for(dindex = 80 ; dindex >= 0 ; dindex --)
		if(ditem[dindex] == sender)
			break;
	
	if(dindex < 0)
		return;
	
	if(cur_question[dindex] != 0)
		return;
	
	NSLog(@"digit item %d clicked", dindex);
	
	int x, y;
	int keypad_x, keypad_y;
	int max_x = 320, max_y = 320;
	
	keypad_x = [keypad contentSize].width / 2;
	keypad_y = [keypad contentSize].height / 2;
	[self get_digit_xy:dindex :&x :&y];

	x -= keypad_x;
	y -= (keypad_y + 15);
	
	if(x < 0)
		x = 0;
	if(y < 0)
		y = 0;
	if(x > max_x - 2 * keypad_x)
		x = max_x - 2 * keypad_x;
	if(y > max_y - 2 * keypad_y)
		y = max_y - 2 * keypad_y;
	
	[keypad runAction:[MoveTo actionWithDuration:0 position:ccp(x,y)]];
	[kmenu runAction:[MoveTo actionWithDuration:0 position:ccp(x,y)]];
	keypad.visible = YES;
	kmenu.visible = YES;
}

- (bool)isExisted:(int)i :(int)j :(char [9][9])myBoard {
	int k;
	int l;
	
	for(k = 0 ; k < 9 ; k ++)
		if(k != j && myBoard[i][k] == myBoard[i][j])
			return YES;
	
	for(k = 0 ; k < 9 ; k ++)
		if(k != i && myBoard[k][j] == myBoard[i][j])
			return YES;
	
	for(k = (i / 3) * 3 ; k < (i / 3) * 3 + 3 ; k ++)
		for(l = (j / 3) * 3 ; l < (j / 3) * 3 + 3 ; l ++)
			if(k != i && l != j && myBoard[k][l] == myBoard[i][j])
				return YES;
	
	return NO;
}

- (bool)isFull:(char [9][9]) myBoard {
	int i, j;
	
	for(i = 0 ; i < 9 ; i ++)
		for(j = 0 ; j < 9 ; j ++)
			if(myBoard[i][j] == 0)
				return NO;
	
	return YES;
}

- (bool)isWin {
	int i, j;
	for(i = 0 ; i < 9 ; i ++)
		for(j = 0 ; j < 9 ; j ++)
			if([self isExisted:i :j :board])
				return NO;
	return YES;
}

- (void)keyboardClicked:(id)sender {
	int i;
	
	for(i = 9 ; i >= 0 ; i --)
		if(kitem[i] == sender)
			break;
	if(i < 0)
		return;
	
	NSLog(@"keyboard item %d clicked", i);
	
	if(dindex < 0 || dindex > 80)
		return;
	
	int x, y;
	x = 1000;
	y = 1000;
	keypad.visible = NO;
	kmenu.visible = NO;
	[keypad runAction:[MoveTo actionWithDuration:0 position:ccp(x,y)]];
	[kmenu runAction:[MoveTo actionWithDuration:0 position:ccp(x,y)]];
	
	char c;
	if(is_alpha_doku)
		c = 'A';
	else
		c = '1';
	
	NSString *str;
	if(i < 9)
		str = [[NSString alloc] initWithFormat:@"%c", c+i];
	else
		str = [[NSString alloc] initWithFormat:@" "];
	
	[ditem[dindex] setString:str];
	
	if(i < 9) {
		board[dindex/9][dindex%9] = i + 1;
		
		bool bExist = [self isExisted:dindex/9 :dindex%9 :board];
		if(bExist)
			[ditem[dindex].label setRGB:0xcc :0x00 :0x00];
		else
			[ditem[dindex].label setRGB:43 :0 :233];
	} else {
		board[dindex/9][dindex%9] = 0;
	}
	
	bool isFull = [self isFull:board];
	if(isFull) {
		if([self isWin]) {
			NSLog(@"You win!");
			[self playNextSound];
		}
	}
}

- (void)switchGame {
	int i;
	
	for(i = 0 ; i < 81 ; i ++)
		if(board[i/9][i%9])
			break;
	if(i != 81)
		return;
	
	if(is_alpha_doku)
		is_alpha_doku = NO;
	else
		is_alpha_doku = YES;
	
	[self updateLevel];
	[self updateKeyboard];
	[self updateCmd];	
}

- (void)lockGame {
	int i;

	for(i = 0 ; i < 81 ; i ++) {
		if(board[i/9][i%9] == 0)
			continue;
		if([self isExisted:i/9 :i%9 :board])
			return;
	}
	
	for(i = 0 ; i < 81 ; i ++) {
		cur_question[i] = board[i/9][i%9];
		if(cur_question[i])
			[ditem[i].label setRGB:0 :0 :0];
	}
	[self updateBoard];
}

- (void)newGame {
	memset(&cur_question, 0, sizeof(cur_question));
	memset(&board, 0, sizeof(board));
	[self resetGame];	
}

- (void)cmdClicked:(id)sender {
	int i;
	
	for(i = 5 ; i >= 0 ; i --)
		if(citem[i] == sender)
			break;
	if(i < 0)
		return;
	
	NSLog(@"cmd item #%d Clicked", i);
	
	switch(i) {
		case 0:
			[self switchGame];
			break;
		case 1:
			[self lockGame];
			break;			
		case 2:
			[self resetGame];
			break;
		case 3:
			[self hintGame];
			break;
		case 4:
			[self newGame];
			break;
		case 5:
			[self unschedule:@selector(update:)];
			[self mainGame];
			break;
	}
}

@end
